﻿//--------------------------------------------------------------------------------------------------------------------- 
// <copyright file="EnsureListData.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights reserved.
// </copyright>
// <summary>
//   Creates (or Updates) a SharePoint List Item.
// </summary>
//---------------------------------------------------------------------------------------------------------------------
namespace Collaboris.Saf.Actions.Wss.ListItem
{
    using System;
    using System.Collections.Generic;

    using Engine;

    using Entities;

    using Microsoft.SharePoint;

    using SharePoint.Wss.Attributes;
    using SharePoint.Wss.Lists;

    using Utils;
    using System.Text.RegularExpressions;

    [CollaborisClass(
        Title = "Ensure List Item",
        ReleaseStatus = ReleaseStatus.Beta,
        DisableDocumentation = true,
        ContactAuthorEmail = "Support@Collaboris.co.uk",
        Summary = "Creates (or updates) a SharePoint list item.",
        Remarks = "This action will locate the list item (in the list) based on name (or id). " +
                  "If no item is found, then a new item will be created in the list. If an item is found " +
                  "it will attempt to update the columns with the values passed in the ListDataInfo.Rows(Dictionary).<br/><br/>All field names " +
                  "are case-sensitive.<br/><br/>This action does nothing on the Undo so a backup is recommended.",
          ClassGuid = "{156E17A5-A7BA-4e1f-8A48-1BC341A7C653}"
        )
    ]
    [Obsolete("This action is no longer supported - do not use.")]
    public class EnsureListData : WSSActionBase<ListDataInfo>
    {
        /// <summary>
        /// Does the action.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        protected override ProcessStatus DoAction(SafContext context, ListDataInfo entity)
        {
            this.ProcessListItem(ProcessMode.Do, entity);

            return ProcessStatus.Success;
        }

        /// <summary>
        /// Gets the list item to update.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        private SPListItemCollection GetListItemsToUpdate(ListDataInfo entity, SPList parentList, 
                                            SerializableObjectDictionary<string> dictionary)
        {
            SPListItemCollection items = null;

            ValidationHelper.VerifyObjectArgument(parentList, "parentList");
   
            if (parentList != null)
            {
                if (string.IsNullOrEmpty(entity.UpdateColumnKey))
                    return null;

                if (entity.ListItemID > 0)
                {
                    items = SPListItemHelper.GetListItems(this.TargetWeb, parentList,
                                        entity.UpdateColumnKey, entity.ListItemID.ToString());
                }else
                {
                    items = SPListItemHelper.GetListItems(this.TargetWeb, parentList,
                                            entity.UpdateColumnKey, (string)dictionary[entity.UpdateColumnKey]);
                }
            }
            return items;
        }

        /// <summary>
        /// Processes the list item.
        /// </summary>
        /// <param name="mode">The mode.</param>
        /// <param name="entity">The entity.</param>
        private void ProcessListItem(ProcessMode mode, ListDataInfo entity)
        {
            if (mode == ProcessMode.Do)
            {
                SPList parentList = null;
                bool listWasEmptied = false;
                parentList = SPListHelper.GetList(this.TargetWeb, entity.ListName);

                if (entity.EmptyListBeforeRun)
                {
                    SPListHelper.DeleteList(TargetWeb, parentList.Title, true);
                    listWasEmptied = true;
                }

                foreach (SerializableObjectDictionary<string> dictionary in entity.Rows)
                {
                    SPListItemCollection itemsToUpdate = null;
                    SPListItem currentListItem = null;

                    if (! listWasEmptied)
                        itemsToUpdate = this.GetListItemsToUpdate(entity, parentList, dictionary);

                    SerializableObjectDictionary<string> stringDictionary = new SerializableObjectDictionary<string>();
                    
                    // Populate the Dictionary from the DataSet
                    if (entity.ListDataSet != null)
                    {   
                        foreach(string key in dictionary.Keys)
                        {   
                            string dictionaryValues = ((string)dictionary[key]);
                            string[] dictionaryValueArray = Regex.Split(dictionaryValues, ";#");
                            
                            string dictionaryValue = string.Empty;
                            foreach (string dictionaryVal in dictionaryValueArray)
                            {                                
                                // Here we call Regex.Match.
                                Match match = Regex.Match(dictionaryVal, @"@ListDataSet{([0-9]*):([0-9]*)}",
                                    RegexOptions.IgnoreCase);
                                if (match.Success)
                                {
                                    int rowNo = Int32.Parse(match.Groups[1].Value);
                                    int colNo = Int32.Parse(match.Groups[2].Value);
                                    if (dictionaryValueArray.Length > 1)
                                    {
                                        if(!string.IsNullOrEmpty(dictionaryValue))
                                            dictionaryValue += ";#";
                                    }
                                    dictionaryValue += entity.ListDataSet.Tables[0].Rows[rowNo].ItemArray[colNo].ToString();
                                }
                                else
                                {
                                    if (dictionaryValueArray.Length > 1)
                                    {
                                        if (!string.IsNullOrEmpty(dictionaryValue))
                                        dictionaryValue += ";#";
                                    }
                                    dictionaryValue += dictionaryVal;
                                }                                
                            }

                            stringDictionary[key] = dictionaryValue;

                        }
                    }
                    else
                    {
                        stringDictionary = dictionary;
                    }
                    
                    // Ok there is no existing list item
                    if (itemsToUpdate == null)
                    {
                        this.Trace.TraceInfo("No existing list item was found for this entity '" + stringDictionary + "'");

                        // lets go add a new item.
                        currentListItem = parentList.Items.Add();
                        this.SetListItemRows(currentListItem, stringDictionary);
                    }
                    else
                    {
                        foreach (SPListItem item in itemsToUpdate)
                        {
                            this.SetListItemRows(item, stringDictionary);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Sets the list item rows.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="listItemToUpdate">The list item to update.</param>
        private void SetListItemRows(SPListItem itemToUpdate, SerializableObjectDictionary<string> dictionary)
        {
            // now lets us loop through the items.
            foreach (string key in dictionary.Keys)
            {
                string rowData = dictionary[key] as string;

                if (!string.IsNullOrEmpty(rowData))
                    itemToUpdate[key] = rowData;
            }

            itemToUpdate.Update();
        }

        /// <summary>
        /// Checks the Data entity used by the Action for Validity
        /// </summary>
        /// <param name="context">The <see cref="SafContext"/> passed in by the SAF Engine.</param>
        /// <param name="entity">The data entity to Validate.</param>
        /// <param name="errors">List of <see cref="ValidationError"/>s</param>
        /// <param name="mode"><see cref="ProcessMode"/>signalling wheter we are Doing, or Undoing the action.</param>
        /// <returns>false if invalid; otherwise true.</returns>
        protected override bool IsValid(SafContext context, ListDataInfo entity, ref List<ValidationError> errors, ProcessMode mode)
        {
            
            int currentCount = errors.Count;

            //// Validate each object now.    

            ValidateObjectForNull(entity.Rows, "ListDataInfo.Rows", ref errors);
            ValidateStringForNull(entity.ListName, "ListDataInfo.ListName", ref errors);

            // Have we added errors ?
            return errors.Count == currentCount;
        }
    }

    
}